/** 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package it.free.i.virtual.machine.hal.devicealias.controller;

import it.free.i.virtual.machine.hal.devicealias.DeviceAliasCommandExecutionException;
import it.free.i.virtual.machine.hal.devicealias.command.DeviceAliasCommand;

import javax.management.AttributeChangeNotification;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;


/**  
 * This is the class observed by all the device alias
 * @author stefano
 */
public final class DeviceAliasController extends NotificationBroadcasterSupport {

	private static final long serialVersionUID = 1206637208827008757L;
	private static DeviceAliasController DEVICE_ALIAS_CONTROLLER_INSTANCE = null;
	//private static Logger logger = Logger.getLogger(DeviceAliasController.class);
	private long sequenceNumber = 0;
	
	/**
	 * Private as for a singleton
	 */
	private DeviceAliasController() {
		super();
	}

	/**
	 * Factory singleton private instance accessor
	 * @return THE instance of this factory
	 */
	public static DeviceAliasController getInstance(){
		if(DEVICE_ALIAS_CONTROLLER_INSTANCE == null){
		   synchronized (DeviceAliasController.class){
			   if(DEVICE_ALIAS_CONTROLLER_INSTANCE == null){
				  DEVICE_ALIAS_CONTROLLER_INSTANCE = new DeviceAliasController(); 
			   }	   
		   }
		}
		return DEVICE_ALIAS_CONTROLLER_INSTANCE;
	}
	
	/**
	 * Execute a command set. This will invoke also the notification to device alias
	 * This is the observer/observable paradigm implementation 
	 * @param commandToExecute is the command that will be fired to pass set with one of the verbs available
	 * @throws DeviceAliasCommandExecutionException 
	 */
	public void fireCommand(DeviceAliasCommand commandToExecute) throws DeviceAliasCommandExecutionException{
	
		//logger.info("Firing a new device aliases command [: " + commandToExecute.toString() + "]");
		
		Notification notification = buildNotification(this, 
													  AttributeChangeNotification.ATTRIBUTE_CHANGE, 
													  "DeviceAliasController command", 
													  commandToExecute);
		
		sendNotification(notification);
		
		//logger.info("Device aliases command [: " + commandToExecute.toString() + "] fired");
	}
	
	/**
	 * Build the notification object with custom params for this application subsystem domain
	 * @param source is the notification generator/sender
	 * @param type is the type of notification sent
	 * @param message is a message associated with this notification
	 * @param command is the command to fire within the notification
	 * @return a notification ready-to-send object
	 */
	private Notification buildNotification(Object source, String type, String message, DeviceAliasCommand command){
		
		Notification notification = new Notification(type,
                									 source,
                									 sequenceNumber,
                									 System.currentTimeMillis(),
                									 message);
		
		notification.setUserData(command);
		
		return notification;
		
	}

}
